#include "vxmovementstate.h"

class MouseCaptureTransition : public QMouseEventTransition
{

	Q_OBJECT

public:
	MouseCaptureTransition(QWidget * widget):
			QMouseEventTransition(widget, QEvent::MouseButtonPress, Qt::LeftButton),
			_widget(widget)
	{
	}


	void onTransition(QEvent *event)
	{
		if (event->type() != QEvent::StateMachineWrapped){
			return;
		}

		QStateMachine::WrappedEvent * wrapped = static_cast<QStateMachine::WrappedEvent *>(event);

		if (wrapped->event()->type() != QEvent::MouseButtonPress){
			return;
		}

		QMouseEvent * mevent = static_cast<QMouseEvent *>(wrapped->event());

		QPoint p = mevent->globalPos() -
				   _widget->mapToGlobal(QPoint(0,0));

		_widget->setProperty("_mpoint", p);
	}

private:
	QWidget * _widget;
};


class MouseMoveTransition : public QMouseEventTransition
{

	Q_OBJECT

public:
	MouseMoveTransition(QWidget * widget) :
			QMouseEventTransition(widget, QEvent::MouseMove, Qt::NoButton),
			_widget(widget)
	{
	}

	void onTransition(QEvent *event)
	{
		if (event->type() != QEvent::StateMachineWrapped){
			return;
		}

		QStateMachine::WrappedEvent * wrapped = static_cast<QStateMachine::WrappedEvent *>(event);

		if (wrapped->event()->type() != QEvent::MouseMove){
			return;
		}

		QMouseEvent * me = static_cast<QMouseEvent *>(wrapped->event());

		QPoint mp = _widget->property("_mpoint").toPoint() +
						_widget->mapToGlobal(QPoint(0,0));

		QPoint p = me->globalPos() - mp;

		emit movement(p.x(), p.y());

	}

signals:
	void movement(int mx, int my);
	void immobility();

private:
	QWidget * _widget;

};


VxMovementState::VxMovementState(QWidget * widget, QState * parent) :
		QState(parent)
{

	QState * stateImmobility = new QState(this);
	QState * stateMouseCapture = new QState(this);
	QState * stateMouseMovement = new QState(this);

	MouseCaptureTransition * trMouseDown = new MouseCaptureTransition(widget);
	trMouseDown->setTargetState(stateMouseCapture);

	QMouseEventTransition * trMouseCaptureToRelease = new QMouseEventTransition(widget, QEvent::MouseButtonRelease, Qt::LeftButton);
	trMouseCaptureToRelease->setTargetState(stateImmobility);

	QMouseEventTransition * trMouseCaptureToMove = new QMouseEventTransition(widget, QEvent::MouseMove, Qt::NoButton);
	trMouseCaptureToMove->setTargetState(stateMouseMovement);

	QMouseEventTransition * trMouseMoveToRelease = new QMouseEventTransition(widget, QEvent::MouseButtonRelease, Qt::LeftButton);
	trMouseMoveToRelease->setTargetState(stateImmobility);

	MouseMoveTransition * trMouseMoveToMove = new MouseMoveTransition(widget);

	stateImmobility->addTransition(trMouseDown);
	stateMouseCapture->addTransition(trMouseCaptureToRelease);
	stateMouseCapture->addTransition(trMouseCaptureToMove);

	stateMouseMovement->addTransition(trMouseMoveToRelease);
	stateMouseMovement->addTransition(trMouseMoveToMove);

	this->setInitialState(stateImmobility);

	connect(trMouseMoveToMove, SIGNAL(movement(int,int)), this, SIGNAL(movement(int,int)));
	connect(stateImmobility, SIGNAL(entered()), this, SIGNAL(immobility()));
	connect(stateMouseMovement, SIGNAL(entered()), this, SIGNAL(immobilityLost()));

}

#include "vxmovementstate.moc"
